//
//  ViewController.m
//  RBIOSBase
//
//  Created by ren on 13/09/2017.
//  Copyright © 2017 bryan. All rights reserved.
//

#import "ViewController.h"
#import "ObjectTest.h"
#import <objc/message.h>
#import "ObjectTest+TestCategory2.h"
#import "Other.h"
#import "SubObjectTest.h"
#import "ImageView.h"
#import <SDWebImage/UIImageView+WebCache.h>
#import "ImageDownloader.h"
#import <CommonCrypto/CommonDigest.h>
#import "ImagesViewController.h"
#import "ThreadObject.h"
#import "NSOperations.h"
#import "TicketsCenter.h"
#import "Seller.h"
#import "InfiniteScrollView.h"
#import "InfiniteCollectionView.h"
#import "FPSView.h"
#import "VerticalInfiniteScrollView.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *specificImageView;
@property (strong, nonatomic, nonnull) NSCache *memCache;
@property (nonatomic, strong) dispatch_queue_t ioQueue;
@property (nonatomic, copy) NSString *diskCachePath;

@property (weak, nonatomic) IBOutlet UIButton *buttonControlOne;
@property (weak, nonatomic) IBOutlet UILabel *labelControlTwo;

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *buttonControlContraintBottom;

@end

@implementation ViewController {
	ObjectTest *objectTest;
	NSFileManager *_fileManager;
}

//- (void)dealloc
//{
//	NSLog(@"%ld", [objectTest retainCount]);
//	[super dealloc];
//}
- (IBAction)buttonAction:(UIButton *)sender {
//	if (self.buttonControlContraintBottom.constant >= 1) {
//		self.buttonControlContraintBottom.constant --;
//	}
//	else {
//		self.buttonControlContraintBottom.constant ++;
//	}
}

+ (void)load
{
	NSLog(@"only once load");
//	[Other printClass];
}

- (void)viewDidLoad {
	[super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
//	[self UIImageOperation];
//	[self drawRect:CGRectZero];
//	[self drawImageView];
//	[self resizableImage:CGRectZero];
//	[self operationPractice];
//	[self addAcquireButton];
//	for (int i = 0; i < INT_MAX; i++) {
//		UIImage *image = [UIImage imageNamed:@"test"];
//	}
	
//	[self.specificImageView setImage:image];
	
//	ThreadObject *threadObject = [ThreadObject new];
//	
//	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//		for (int i = 0; i < 10000; i++) {
//			[threadObject setIncreaseInt:i];
//		}
//	});
//	
//	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//		for (int j = 0; j < 10000; j++) {
//			[threadObject increaseInt];
//		}
//	});
	
//	NSOperations *operation = [NSOperations new];
//	[operation operations];

//	TicketsCenter *ticketsCenter = [TicketsCenter new];
//	ticketsCenter.tickets = 15;
//	Seller *seller = [[Seller alloc] initWith:ticketsCenter sname:@"销售点-->1"];
//	Seller *seller1 = [[Seller alloc] initWith:ticketsCenter sname:@"销售点-->2"];
//	Seller *seller2 = [[Seller alloc] initWith:ticketsCenter sname:@"销售点-->3"];
//	Seller *seller3 = [[Seller alloc] initWith:ticketsCenter sname:@"销售点-->4"];
//
//	dispatch_queue_t queue = dispatch_queue_create("com.bryan.queue", DISPATCH_QUEUE_CONCURRENT);
//	dispatch_async(queue, ^{
//		[seller startSell];
//	});
//
//	dispatch_async(queue, ^{
//		[seller1 startSell];
//	});
//
//	dispatch_async(queue, ^{
//		[seller2 startSell];
//	});
//
//	dispatch_async(queue, ^{
//		[seller3 startSell];
//	});
//	[self addInfiniteScrollView];
//	[self addInfiniteCollectionView];
	FPSView *fpsView = [[FPSView alloc] initWithFrame:CGRectMake(0, 200, 100, 20)];
	[self.view addSubview:fpsView];
	
	[self addVerticalInfiniteScrollView];
}

- (void)addVerticalInfiniteScrollView
{
	VerticalInfiniteScrollView *scrollView = [[VerticalInfiniteScrollView alloc] initWithFrame:CGRectMake(0, 80, self.view.bounds.size.width, 40)];
	[scrollView setTitleList:@[@"-->1、看看这个滚动视图123456", @"-->2、看看这个滚动视图1234567", @"-->3、看看这个滚动视图123456"]];
	[scrollView setScrollStyle:YES];
	[self.view addSubview:scrollView];
}


//- (void)addInfiniteCollectionView
//{
//	InfiniteCollectionView *collectionView = [[InfiniteCollectionView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 100)];
//	[self.view addSubview:collectionView];
//}

//- (void)addInfiniteScrollView
//{
//	NSArray *imageList = [NSArray arrayWithObjects:[UIImage imageNamed:@"me"], [UIImage imageNamed:@"test"], [UIImage imageNamed:@"timg"], [UIImage imageNamed:@"test1"], [UIImage imageNamed:@"test2"], nil];//
//	InfiniteScrollView *scrollView = [[InfiniteScrollView alloc] init];
//	[scrollView setImageList:imageList];
//	[scrollView setScrollStyle:1 autoScroll:YES];
//	[self.view addSubview:scrollView];
//	
//}


- (void)operationPractice
{
	ImageDownloader *imageDownloader = [ImageDownloader new];
	[imageDownloader addOperationBlock];
}

- (void)initImageDownloadIO
{
	_ioQueue = dispatch_queue_create("com.rbiosbase.imageCache", DISPATCH_QUEUE_SERIAL);
	NSString *fullNamespace = [@"com.rbiosbase.imageCache." stringByAppendingString:@"RBIOSBaseCache"];
	_memCache = [NSCache new];
	_memCache.name = fullNamespace;
	_diskCachePath = [self diskFilePath:fullNamespace];
	dispatch_async(_ioQueue, ^{
		_fileManager = [NSFileManager new];
	});
	[self sdWebImage];
	[self addAcquireButton];
}

- (void)sdWebImage
{
//	[self.specificImageView sd_setImageWithURL:[NSURL URLWithString:@"http://wx.qlogo.cn/mmhead/ver_1/bI1ezaHJ2eibyOdLHZ2YTNVIn1YeMBGYafN4seTxAhghwcCVzL5FWho2dlSIJRKpv53k4jVJA9vYdzPM7hOgC34avEOlq0PzsnaUAlvGqVlU/132"]];
	
	NSString *urlKey = @"http://wx.qlogo.cn/mmhead/ver_1/bI1ezaHJ2eibyOdLHZ2YTNVIn1YeMBGYafN4seTxAhghwcCVzL5FWho2dlSIJRKpv53k4jVJA9vYdzPM7hOgC34avEOlq0PzsnaUAlvGqVlU/132";
	[self acquireCache:urlKey];
	
	ImageDownloader *imageDownloader = [ImageDownloader new];
	imageDownloader.reciverImage = ^(NSData *data, NSString *urlKey) {
		UIImage *image = [UIImage imageWithData:data];
		[self.specificImageView setImage:image];
		if (self.memCache) {
			[self.memCache setObject:image forKey:urlKey];
		}
		dispatch_async(_ioQueue, ^{
			if (_fileManager) {
				[self saveToDisk:data forKey:urlKey];
			}
		});
	};
	[imageDownloader genURLSession];
}

- (void)addAcquireButton
{
	UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
	button.frame = CGRectMake(100, 400, 80, 40);
	[button setBackgroundColor:[UIColor redColor]];
	[button setTitle:@"获取缓存数据" forState:UIControlStateNormal];
	[button addTarget:self action:@selector(forwardImages) forControlEvents:UIControlEventTouchUpInside];
	[self.view addSubview:button];
}

- (void)forwardImages
{
	ImagesViewController *imagesVC = [ImagesViewController new];
	[self presentViewController:imagesVC animated:YES completion:^{
		
	}];
}

- (void)acquireCache:(NSString *)key
{
	[self.specificImageView setImage:nil];
	id memImage = [self.memCache objectForKey:key];
	if ([memImage isKindOfClass:[UIImage class]]) {
		UIImage *image = (UIImage *)memImage;
		[self.specificImageView setImage:image];
	}
	else {
		dispatch_async(_ioQueue, ^{
			NSString *cachePathForKey = [self defaultCachePathForKey:key];
			NSData *fileData = [_fileManager contentsAtPath:cachePathForKey];
			if (fileData) {
				UIImage *image = [UIImage imageWithData:fileData];
				if (self.memCache) {
					[self.memCache setObject:image forKey:key];
				}
				dispatch_async(dispatch_get_main_queue(), ^{
					[self.specificImageView setImage:image];
				});
			}
		});
	}
}

- (NSString *)diskFilePath:(NSString *)fullNamePath
{
	NSArray<NSString *> *filePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
	return [[filePath objectAtIndex:0] stringByAppendingString:fullNamePath];
}

- (void)saveToDisk:(NSData *)imageData forKey:(NSString *)key
{
	if (![_fileManager fileExistsAtPath:_diskCachePath]) {
		[_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
	}
	
	NSString *cachePathForKey = [self defaultCachePathForKey:key];
	NSURL *fileURL = [NSURL fileURLWithPath:cachePathForKey];
	
	[_fileManager createFileAtPath:cachePathForKey contents:imageData attributes:nil];
	
	[fileURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
	
}

- (NSString *)defaultCachePathForKey:(NSString *)key {
	return [self cachePathForKey:key inPath:self.diskCachePath];
}

- (NSString *)cachePathForKey:(NSString *)key inPath:(nonnull NSString *)path
{
	NSString *filename = [self cachedFileNameForKey:key];
	return [path stringByAppendingString:filename];
}

- (NSString *)cachedFileNameForKey:(NSString *)key {
	const char *str = key.UTF8String;
	if (str == NULL) {
		str = "";
	}
	
	unsigned char r[CC_MD5_DIGEST_LENGTH];
	CC_MD5(str, (CC_LONG)strlen(str), r);
	NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%@",
						  r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10],
						  r[11], r[12], r[13], r[14], r[15], [key.pathExtension isEqualToString:@""] ? @"" : [NSString stringWithFormat:@".%@", key.pathExtension]];
	return filename;
	
}

- (void)UIImageOperation
{
//	使用场合：
//
//	1、图片比较小，使用频率比较高；
//	2、建议把需要缓存的图片放到Assets.xcassets里面，Assets.xcassets默认就是带有缓存的。
//	3、图片被imageNamed:这种方式加载之后，该UIImage对象会一直被系统一个强指针指向，就算我们设置该UIImage对象为空，仍不能释放该内存空间。
//	for (int i = 0; i < INT_MAX; i++) {
//		UIImage *image = [UIImage imageNamed:@"timg"];//内存会暴增 同UIView的初始化，因为系统不会主动释放UIView实例对象
//		UIImage *image = [UIImage new];//内存没有明显增长
//	}

	UIImage *image = [UIImage imageNamed:@"timg"];//有缓存
	NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"sunset" ofType:@"jpg"];//这里需要加类型，可以把类型和名称放在一起加在Resource之后 这个文件是在sandbox（沙盒）中
	
	image = [UIImage imageNamed:@"test"];//Assets.xcassets中图片资源只能通过imageNamed来访问
	
	NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"imagasset" ofType:@"bundle"];
	NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
//	NSString *resource = [bundle pathForResource:@"test1" ofType:@"jpg"];
	UITraitCollection *traitCollection = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassRegular];
	image = [UIImage imageNamed:@"test1.jpg" inBundle:bundle compatibleWithTraitCollection:traitCollection];//png的图片不需要指定后缀，非png得图片需要指定后缀 bundle如果不指定，会去app的mainBundle中搜索，UITraitCollection:http://blog.csdn.net/wliu6/article/details/46989505
	
//	不缓存：imageWithContentsOfFile:
//	必须传入图片文件的全名（全路径＋文件名）。
//	无法加载Images.xcassets中的图片。
	image = [UIImage imageWithContentsOfFile:imagePath];
	
	NSData *data = [NSData dataWithContentsOfFile:imagePath];
	image = [UIImage imageWithData:data];
	
	NSString *test2Path = [bundle pathForResource:@"test2" ofType:@"jpg"];
	NSData *test2Data = [NSData dataWithContentsOfFile:test2Path];
	
	image = [UIImage imageWithData:test2Data scale:2];//对图片进行缩放
	
	NSString *test3Path = [bundle pathForResource:@"test3" ofType:@"jpg"];
	NSData *test3Data = [NSData dataWithContentsOfFile:test3Path];
	UIImage *test3Image = [UIImage imageWithData:test3Data];
	image = [UIImage imageWithCGImage:test3Image.CGImage];//CoreGraphics
	image = [UIImage imageWithCGImage:test3Image.CGImage scale:1 orientation:UIImageOrientationLeft];
	
	NSString *test4Path = [bundle pathForResource:@"test4" ofType:@"jpg"];
	NSData *test4Data = [NSData dataWithContentsOfFile:test4Path];
//	UIImage *test4Image = [UIImage imageWithData:test4Data];
	image = [UIImage imageWithCIImage:[CIImage imageWithData:test4Data]];
	
//	image = [UIImage imageWithCIImage:[CIImage imageWithData:test4Data] scale:1.0 orientation:UIImageOrientationUpMirrored];//镜面
	
//	UIImageOrientation orientation = image.imageOrientation;
	
//	image = [UIImage animatedImageNamed:@"loading" duration:13];//只需要把一系列图片按一定序列命名，这个序列要从0或1开始，命名之后只需要把图片名称不含数字的部分写入即可，例如loading1、loading2、loading3……，只需要写入loading。后面是整个动画的时间。
//	image = [UIImage animatedResizableImageNamed:@"loading" capInsets:UIEdgeInsetsZero duration:3.0];
//	
//	image = [UIImage animatedResizableImageNamed:@"loading" capInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeStretch duration:3.0];//可以在capInsets基础上，进行平铺和展开
	
//	NSMutableArray<UIImage *> *images = [NSMutableArray<UIImage *> array];
//	for (int i = 1; i <= 75; i++) {
////		srandom((unsigned int)time(0));
////		long randI = arc4random()%75+1;
//		UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"loading%d", i]];
//		[images addObject:image];
//	}
//	image = [UIImage animatedImageWithImages:images duration:4.0];
	
//	UIGraphicsBeginImageContextWithOptions(image.size, NO, [UIScreen mainScreen].scale);
	UIGraphicsBeginImageContext(image.size);
	[image drawAtPoint:CGPointMake(60, 10)];
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	
	
	UIImage *newImage1 = [self createImageColor:[UIColor redColor] size:CGSizeMake(200, 200)];
	newImage = [ViewController scaleImage:newImage1 scale:0.2];
	
//	newImage = [ViewController waterAtImage:newImage text:@"test水印" point:CGPointMake(10,10) attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:6.0]}];
	
//	[newImage drawAsPatternInRect:CGRectMake(0, 0, 200, 200)];
	
	[self.specificImageView setImage:newImage];
	
	for (int i = 0; i < INT_MAX; i++) {
		@autoreleasepool {//在这里加入自动释放池，不管有没有图片资源，内存都不再暴涨，说明image对象在这个释放池里被释放了
			UIImage *image = [UIImage imageNamed:@"test"];
		}
	}
	
}

- (void)drawImageView
{
	ImageView *imageView = [[ImageView alloc] initWithFrame:self.view.bounds];
	[imageView setBackgroundColor:[UIColor greenColor]];
//	[imageView drawPoint:CGRectZero];
	[imageView drawRect:CGRectZero];
	[self.view addSubview:imageView];
}

- (void)resizableImage:(CGRect)rect
{
	UIImage *image = [UIImage imageNamed:@"me"];
	image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
	[self.specificImageView setImage:image];
}

- (UIImage *)createImageColor:(UIColor *)color size:(CGSize)size {
	UIGraphicsBeginImageContextWithOptions(size, NO, 0);
	UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, size.width, size.height)];
	[color setFill];
	[path fill];
	
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	return newImage;
}

+ (UIImage *)scaleImage:(UIImage *)image scale:(CGFloat)scale {
	CGFloat scaleWidth = image.size.width * scale;
	CGFloat scaleHeight = image.size.height * scale;
	CGSize scaleSize = CGSizeMake(scaleWidth, scaleHeight);
	
	UIGraphicsBeginImageContext(scaleSize);
	[image drawInRect:CGRectMake(0, 0, scaleWidth, scaleHeight)];//CGRectMake(0, 0, scaleWidth, scaleHeight) CGPointMake(30, 30)
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	
	return newImage;
}

+ (UIImage *)waterAtImage:(UIImage *)image text:(NSString *)text point:(CGPoint)point attributes:(NSDictionary *)attributes
{
	UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
	[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
	[text drawAtPoint:point withAttributes:attributes];
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	return newImage;
}

- (void)nsobjectOperation
{
	objectTest = [ObjectTest new];
//	[SubObjectTest load];
//	SubObjectTest *subObjectTest = [SubObjectTest new];
//	[subObjectTest overrideVirtualMethod];//这个方法在superclass中因为实现了doesNotRecognizeSelector，所以在子类中必须重写，否则会报nrecognized selector错误
//	
//	[objectTest performSelector:@selector(printDescription)];
//	objc_msgSend(objectTest, @selector(printDescription));
//	NSLog(@"class---->%p-->%d", [ObjectTest class], [[NSProxy alloc] isProxy]);//isProxy检查是否不继承自NSObject(比如NSProxy)，YES为不继承，返回NO说明继承
//	
//	if ([objectTest isMemberOfClass:[ObjectTest class]]) {
//		NSLog(@"123123--->true");
//	}
//	
//	if ([objectTest conformsToProtocol:@protocol(ObjectTestProtocol)]) {//NSProtocolFromString(@"ObjectTestProtocol")
//		NSLog(@"ObjectTestProtocol---->123123--->true");
//	}
//	
//	if ([objectTest respondsToSelector:NSSelectorFromString(@"printDescription")]) {//@selector(printDescription)
//		NSLog(@"printDescription---->123123--->true");//@selector(printDescription)
//	}
//	NSLog(@"class isa--->%p",object_getClass(objectTest));//isa
//	NSLog(@"%ld", [objectTest retainCount]);
//	[objectTest release];
	//respondsToSelector,可以通过类实例对象和类对象来调用
	NSLog(@"objc respondsToSelector instance method ----> %d",[objectTest respondsToSelector:@selector(printDescription)]);//如果通过类实例调用，同instancesRespondToSelector一样的效果
	NSLog(@"objc respondsToSelector class method ----> %d",[ObjectTest respondsToSelector:@selector(printDesc)]);//objectTest
	//instancesRespondToSelector,可以通过类对象来调用
	NSLog(@"objc respondsToSelector instance method ----> %d",[ObjectTest instancesRespondToSelector:@selector(printDescription)]);
	NSLog(@"objc respondsToSelector class method ----> %d",[ObjectTest instancesRespondToSelector:@selector(printDesc)]);
	
	IMP imp = [ObjectTest methodForSelector:@selector(printDesc)];
	Method method = class_getInstanceMethod([self class], @selector(testPrintDescIMP));
	method_setImplementation(method, imp);
	[self testPrintDescIMP];
	
	//	[objectTest testUnrecognizedSelector];
	//	[objectTest performSelector:@selector(testUnrecognizedSelector)];
	[ObjectTest testClassMethod];
}

- (void)testPrintDescIMP
{
	NSLog(@"testPrintDescIMp");
}


- (void)didReceiveMemoryWarning {
	[super didReceiveMemoryWarning];
	// Dispose of any resources that can be recreated.
}


@end
